class WebVideoOptimizer {
    constructor() {
        this.ffmpeg = null;
        this.currentFile = null;
        this.isProcessing = false;
        this.maxMemoryUsage = 256 * 1024 * 1024; // 256MB
        this.chunkSize = 64 * 1024 * 1024; // 64MB chunks
        this.workers = [];
        this.maxWorkers = navigator.hardwareConcurrency || 4;
        this.init();
    }

    init() {
        this.setupEventListeners();
        this.loadFFmpeg();
        // 启动内存监控
        this.startMemoryMonitoring();
        // 检查现代API支持
        this.checkModernAPISupport();
        // 启用SharedArrayBuffer优化（如果支持）
        this.enableSharedArrayBufferOptimization();
    }

    startMemoryMonitoring() {
        // 每5秒更新一次内存显示
        setInterval(() => {
            if (performance.memory) {
                const memoryInfo = document.getElementById('memoryInfo');
                if (memoryInfo) {
                    const used = Math.round(performance.memory.usedJSHeapSize / 1024 / 1024);
                    const limit = Math.round(performance.memory.jsHeapSizeLimit / 1024 / 1024);
                    const percentage = Math.round((used / limit) * 100);
                    memoryInfo.textContent = `内存使用: ${used}MB / ${limit}MB (${percentage}%)`;

                    // 根据使用率设置颜色
                    if (percentage > 80) {
                        memoryInfo.style.color = '#dc3545';
                    } else if (percentage > 60) {
                        memoryInfo.style.color = '#ffc107';
                    } else {
                        memoryInfo.style.color = '#28a745';
                    }
                }
            }
        }, 5000);
    }

    setupEventListeners() {
        const dropZone = document.getElementById('dropZone');
        const fileInput = document.getElementById('fileInput');
        const selectBtn = document.getElementById('selectBtn');

        // 文件拖拽
        dropZone.addEventListener('dragover', (e) => {
            e.preventDefault();
            dropZone.classList.add('drag-over');
        });

        dropZone.addEventListener('dragleave', () => {
            dropZone.classList.remove('drag-over');
        });

        dropZone.addEventListener('drop', (e) => {
            e.preventDefault();
            dropZone.classList.remove('drag-over');
            const files = e.dataTransfer.files;
            if (files.length > 0) {
                this.handleFile(files[0]);
            }
        });

        // 文件选择
        fileInput.addEventListener('change', (e) => {
            if (e.target.files.length > 0) {
                this.handleFile(e.target.files[0]);
            }
        });

        // 点击拖拽区域选择文件
        dropZone.addEventListener('click', (e) => {
            // 如果点击的是按钮，不要触发区域点击
            if (e.target === selectBtn) {
                return;
            }
            this.openFileSelector();
        });

        // 选择按钮点击事件
        if (selectBtn) {
            selectBtn.addEventListener('click', (e) => {
                e.stopPropagation(); // 阻止事件冒泡
                this.openFileSelector();
            });
        }
    }

    // 检查现代API支持
    checkModernAPISupport() {
        const support = {
            fileSystemAccess: 'showOpenFilePicker' in window,
            streams: 'ReadableStream' in window && 'WritableStream' in window,
            webWorkers: 'Worker' in window,
            sharedArrayBuffer: 'SharedArrayBuffer' in window,
            transferableObjects: 'postMessage' in window
        };
        this.log('现代API支持情况:');
        Object.entries(support).forEach(([api, supported]) => {
            this.log(`  ${api}: ${supported ? '✅' : '❌'}`);
        });
        return support;
    }

    // 启用SharedArrayBuffer优化
    enableSharedArrayBufferOptimization() {
        if ('SharedArrayBuffer' in window) {
            this.log('✅ SharedArrayBuffer可用，启用内存共享优化');
            this.useSharedMemory = true;
        } else {
            this.log('❌ SharedArrayBuffer不可用，使用标准内存管理');
            this.useSharedMemory = false;
        }
    }

    // 智能文件选择器（支持现代API）
    async openFileSelector() {
        // 尝试使用File System Access API（支持更大文件）
        if ('showOpenFilePicker' in window) {
            try {
                this.log('使用File System Access API选择文件...');
                const [fileHandle] = await window.showOpenFilePicker({
                    types: [{
                        description: '视频文件',
                        accept: {
                            'video/*': ['.mp4', '.mov', '.avi', '.mkv', '.webm', '.m4v', '.3gp', '.flv']
                        }
                    }],
                    multiple: false
                });
                const file = await fileHandle.getFile();
                this.log(`通过File System Access API选择文件: ${file.name} (${this.formatFileSize(file.size)})`);
                this.handleFile(file);
                return;
            } catch (error) {
                if (error.name !== 'AbortError') {
                    this.log('File System Access API失败，使用传统方法: ' + error.message);
                }
            }
        }
        // 降级到传统文件选择
        const fileInput = document.getElementById('fileInput');
        fileInput.click();
    }

    async loadFFmpeg() {
        try {
            this.log('正在加载 FFmpeg...');

            // 更新状态文本
            const statusText = document.getElementById('statusText');
            if (statusText) {
                statusText.textContent = '正在加载 FFmpeg...';
            }

            // 等待 FFmpeg 库加载完成
            let attempts = 0;
            const maxAttempts = 10;

            while (typeof FFmpeg === 'undefined' && attempts < maxAttempts) {
                this.log(`等待 FFmpeg 库加载... (${attempts + 1}/${maxAttempts})`);
                await new Promise(resolve => setTimeout(resolve, 1000));
                attempts++;
            }

            if (typeof FFmpeg === 'undefined') {
                throw new Error('FFmpeg 库加载失败，请检查网络连接或刷新页面重试');
            }

            this.log('FFmpeg 库已加载，开始初始化...');

            this.log('创建 FFmpeg 实例...');
            this.ffmpeg = FFmpeg.createFFmpeg({
                log: true,
                corePath: 'https://unpkg.com/@ffmpeg/core@0.10.0/dist/ffmpeg-core.js'
            });

            // 设置日志回调
            this.ffmpeg.setLogger(({ message }) => {
                console.log('FFmpeg:', message);
                if (message.includes('Downloading') || message.includes('Loading')) {
                    this.log(`FFmpeg: ${message}`);
                }
            });

            // 设置进度回调
            this.ffmpeg.setProgress(({ ratio }) => {
                if (this.isProcessing) {
                    const percent = Math.round(40 + ratio * 50); // 40-90% 的范围
                    this.updateProgress(percent, '正在处理视频...');
                }
            });

            // 加载 FFmpeg
            this.log('开始加载 FFmpeg 核心...');
            if (statusText) {
                statusText.textContent = '正在下载 FFmpeg 核心文件...';
            }

            await this.ffmpeg.load();

            this.log('FFmpeg 加载完成！');

            // 启用选择按钮
            const selectBtn = document.getElementById('selectBtn');
            if (selectBtn) {
                selectBtn.disabled = false;
                selectBtn.textContent = '选择视频文件';
            }

            // 更新状态文本
            if (statusText) {
                statusText.textContent = 'FFmpeg 已就绪，可以选择文件';
            }
        } catch (error) {
            console.error('FFmpeg 加载失败:', error);
            this.showError('FFmpeg 加载失败: ' + error.message + '。请确保网络连接正常并刷新页面重试');
        }
    }

    handleFile(file) {
        if (!this.isVideoFile(file)) {
            this.showError('请选择视频文件');
            return;
        }

        // 显示文件大小信息
        this.log('文件已选择: ' + file.name + ' (' + this.formatFileSize(file.size) + ')');

        if (file.size > 1024 * 1024 * 1024) { // 1GB
            this.log(`⚠️ 大文件提示: ${this.formatFileSize(file.size)} - 处理可能需要较长时间`);
            this.log('💡 大文件优化建议：');
            this.log('   • 关闭其他浏览器标签页释放内存');
            this.log('   • 确保有足够的系统内存');
            this.log('   • 处理过程中请勿切换标签页');
        }

        // 检查极端大小限制
        const maxFileSize = 10 * 1024 * 1024 * 1024; // 10GB
        if (file.size > maxFileSize) {
            this.showError(`文件过大！当前文件: ${this.formatFileSize(file.size)}，最大支持: ${this.formatFileSize(maxFileSize)}。建议使用桌面版 FFmpeg 处理超大文件。`);
            return;
        }

        // 根据文件大小给出不同的处理策略提示
        if (file.size > 2 * 1024 * 1024 * 1024) { // 2GB以上
            this.log('🔄 超大文件模式: 将使用流式处理，内存占用更低但处理时间较长');
        } else if (performance.memory) {
            const availableMemory = performance.memory.jsHeapSizeLimit - performance.memory.usedJSHeapSize;
            const estimatedNeeded = file.size * 2.5; // 估算需要的内存

            if (estimatedNeeded > availableMemory) {
                this.log(`⚠️ 内存警告: 估算需要 ${this.formatFileSize(estimatedNeeded)}，可用 ${this.formatFileSize(availableMemory)}`);
                this.log('将自动使用内存优化模式处理');
            }
        }

        this.currentFile = file;
        this.showFileInfo(file);

        // 等待 FFmpeg 加载完成后再开始处理
        if (this.ffmpeg && this.ffmpeg.isLoaded()) {
            this.startProcessing();
        } else {
            this.log('等待 FFmpeg 加载完成...');
            this.waitForFFmpegAndProcess();
        }
    }

    async waitForFFmpegAndProcess() {
        let attempts = 0;
        const maxAttempts = 30; // 最多等待30秒

        while (attempts < maxAttempts) {
            if (this.ffmpeg && this.ffmpeg.isLoaded()) {
                this.log('FFmpeg 已准备就绪，开始处理...');
                this.startProcessing();
                return;
            }

            await new Pronmise(resolve => setTimeout(resolve, 1000));
            attempts++;
            this.log(`等待 FFmpeg 加载... (${attempts}/${maxAttempts})`);
        }

        this.showError('FFmpeg 加载超时，请刷新页面重试');
    }

    isVideoFile(file) {
        return file.type.startsWith('video/');
    }

    showFileInfo(file) {
        document.getElementById('fileName').textContent = file.name;
        document.getElementById('fileSize').textContent = this.formatFileSize(file.size);
        document.getElementById('fileType').textContent = file.type;
        document.getElementById('fileInfo').style.display = 'block';
    }

    formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes';
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }

    // 监控内存使用情况
    logMemoryUsage(stage) {
        if (performance.memory) {
            const used = Math.round(performance.memory.usedJSHeapSize / 1024 / 1024);
            const total = Math.round(performance.memory.totalJSHeapSize / 1024 / 1024);
            const limit = Math.round(performance.memory.jsHeapSizeLimit / 1024 / 1024);
            this.log(`内存使用 [${stage}]: ${used}MB / ${total}MB (限制: ${limit}MB)`);

            // 更新内存显示
            const memoryInfo = document.getElementById('memoryInfo');
            if (memoryInfo) {
                const percentage = Math.round((used / limit) * 100);
                memoryInfo.textContent = `内存使用: ${used}MB / ${limit}MB (${percentage}%)`;

                // 根据使用率设置颜色
                if (percentage > 80) {
                    memoryInfo.style.color = '#dc3545';
                } else if (percentage > 60) {
                    memoryInfo.style.color = '#ffc107';
                } else {
                    memoryInfo.style.color = '#28a745';
                }
            }

            // 内存使用警告
            if (used / limit > 0.8) {
                this.log('⚠️ 内存使用率超过80%，可能影响性能');
            }
        }
    }

    async startProcessing() {
        if (!this.ffmpeg) {
            this.showError('FFmpeg 未初始化');
            return;
        }

        if (!this.ffmpeg.isLoaded()) {
            this.showError('FFmpeg 未加载完成，请稍后重试');
            return;
        }

        if (this.isProcessing) {
            this.log('正在处理中，请稍候...');
            return;
        }

        this.isProcessing = true;

        // 禁用选择按钮
        const selectBtn = document.getElementById('selectBtn');
        if (selectBtn) {
            selectBtn.disabled = true;
            selectBtn.textContent = '处理中...';
        }

        this.showProcessSection();
        this.log('开始处理视频文件...');
        this.logMemoryUsage('开始处理');

        try {
            await this.processVideo();
        } catch (error) {
            console.error('视频处理失败:', error);
            this.logMemoryUsage('处理失败');
            this.showError('视频处理失败: ' + error.message);

            // 重新启用按钮
            if (selectBtn) {
                selectBtn.disabled = false;
                selectBtn.textContent = '选择视频文件';
            }
        } finally {
            this.isProcessing = false;
        }
    }

    async processVideo() {
        return await this.processWithProgress(this.currentFile, {
            onStart: () => {
                this.log('开始视频优化处理...');
                this.updateProgress(0, '初始化处理...');
            },
            onProgress: (progress, message) => {
                this.updateProgress(progress * 100, message);
            },
            onComplete: (result) => {
                this.log('视频优化处理完成');
            },
            onError: (error) => {
                this.log('处理失败: ' + error.message);
                throw error;
            }
        });
    }

    // 渐进式处理主方法
    async processWithProgress(file, callbacks = {}) {
        const {
            onStart = () => {},
            onProgress = () => {},
            onComplete = () => {},
            onError = () => {}
        } = callbacks;

        try {
            onStart();

            // 使用真实的文件名，但确保安全
            const originalName = file.name;
            const baseName = originalName.replace(/\.[^/.]+$/, ''); // 去掉扩展名
            const extension = this.getFileExtension(originalName);

            // 创建安全的文件名（移除特殊字符）
            const safeBaseName = baseName.replace(/[^a-zA-Z0-9\u4e00-\u9fa5_-]/g, '_');
            const inputFileName = safeBaseName + '.' + extension;
            const outputFileName = safeBaseName + '_faststart.' + extension;

            this.log('处理文件: ' + originalName);
            this.log('输入文件名: ' + inputFileName);
            this.log('输出文件名: ' + outputFileName);

            // 第一步：分析文件结构 (0-10%)
            onProgress(0.05, '分析文件结构...');
            const metadata = await this.analyzeFile(file);

            // 第二步：检查是否需要处理 (10-15%)
            onProgress(0.1, '检查文件格式...');
            if (await this.isAlreadyOptimized(metadata)) {
                onProgress(1.0, '文件已经优化，无需处理');
                onComplete(file);
                return file;
            }

            // 第三步：准备处理环境 (15-20%)
            onProgress(0.15, '准备处理环境...');
            
            // 检查文件是否仍然可访问
            if (!file || file.size === 0) {
                throw new Error('文件不可访问或已损坏');
            }

            // 强制垃圾回收（如果可用）
            if (window.gc) {
                window.gc();
            }

            // 第四步：智能选择处理策略并执行 (20-80%)
            onProgress(0.2, '开始优化处理...');
            
            if (file.size > 100 * 1024 * 1024) { // 100MB以上使用智能策略
                this.log('大文件，使用智能处理策略...');
                await this.processFileWithBestMethod(file, inputFileName);
            } else {
                this.log('小文件，使用标准处理...');
                await this.directProcess(file, inputFileName);
            }

            // 第五步：验证输入文件 (75-80%)
            onProgress(0.75, '验证输入文件...');
            await this.validateInputFile(inputFileName);

            // 第六步：执行FFmpeg优化 (80-90%)
            onProgress(0.8, '执行视频优化...');
            await this.optimizeWithFFmpeg(inputFileName, outputFileName, (progress) => {
                onProgress(0.8 + progress * 0.1, '正在优化视频...');
            });

            // 第七步：验证和输出结果 (90-100%)
            onProgress(0.9, '验证处理结果...');
            const outputData = await this.validateAndGetResult(outputFileName);

            // 清理临时文件
            this.cleanupTempFiles(inputFileName, outputFileName);

            onProgress(1.0, '处理完成');
            
            // 创建下载链接
            this.createDownloadLink(outputData, originalName, baseName + '_faststart.' + extension);
            
            const result = new Blob([outputData.buffer], { type: 'video/mp4' });
            onComplete(result);

            // 显示结果界面
            this.showResult();
            this.logMemoryUsage('处理完成');

            // 强制垃圾回收
            if (window.gc) {
                window.gc();
                this.logMemoryUsage('垃圾回收后');
            }

            return result;

        } catch (error) {
            onError(error);
            throw error;
        }
    }

    // 分析文件结构
    async analyzeFile(file) {
        this.log(`分析文件: ${file.name} (${this.formatFileSize(file.size)})`);
        
        // 读取文件头部信息来分析格式
        const headerSize = Math.min(1024 * 1024, file.size); // 读取前1MB或整个文件
        const header = await file.slice(0, headerSize).arrayBuffer();
        const headerView = new Uint8Array(header);
        
        // 检查文件格式标识
        const metadata = {
            size: file.size,
            type: file.type,
            isMP4: this.checkMP4Format(headerView),
            hasFastStart: this.checkFastStartFlag(headerView)
        };
        
        this.log(`文件格式: ${metadata.isMP4 ? 'MP4' : '其他'}`);
        this.log(`FastStart状态: ${metadata.hasFastStart ? '已优化' : '未优化'}`);
        
        return metadata;
    }

    // 检查MP4格式
    checkMP4Format(headerView) {
        // 检查ftyp box
        for (let i = 0; i < Math.min(headerView.length - 8, 1000); i++) {
            if (headerView[i] === 0x66 && headerView[i+1] === 0x74 && 
                headerView[i+2] === 0x79 && headerView[i+3] === 0x70) {
                return true;
            }
        }
        return false;
    }

    // 检查FastStart标志
    checkFastStartFlag(headerView) {
        // 简单检查：如果moov box在文件开头附近，可能已经优化
        for (let i = 0; i < Math.min(headerView.length - 8, 10000); i++) {
            if (headerView[i] === 0x6D && headerView[i+1] === 0x6F && 
                headerView[i+2] === 0x6F && headerView[i+3] === 0x76) {
                return i < 1000; // 如果moov在前1KB内，认为已优化
            }
        }
        return false;
    }

    // 检查是否已经优化
    async isAlreadyOptimized(metadata) {
        return metadata.isMP4 && metadata.hasFastStart;
    }

    // 预处理验证输入文件
    async validateInputFile(fileName) {
        try {
            const inputData = this.ffmpeg.FS('readFile', fileName);
            this.log(`验证输入文件: ${fileName} (${this.formatFileSize(inputData.length)})`);
            
            if (inputData.length === 0) {
                throw new Error('输入文件为空');
            }
            
            // 检查文件头
            const header = new Uint8Array(inputData.buffer.slice(0, Math.min(64, inputData.length)));
            let isValidFormat = false;
            
            // 检查各种视频格式标识
            for (let i = 0; i < header.length - 4; i++) {
                // MP4/MOV格式 (ftyp box)
                if (header[i] === 0x66 && header[i+1] === 0x74 && 
                    header[i+2] === 0x79 && header[i+3] === 0x70) {
                    isValidFormat = true;
                    this.log('检测到MP4/MOV格式');
                    break;
                }
                // AVI格式
                if (header[i] === 0x52 && header[i+1] === 0x49 && 
                    header[i+2] === 0x46 && header[i+3] === 0x46) {
                    isValidFormat = true;
                    this.log('检测到AVI格式');
                    break;
                }
            }
            
            if (!isValidFormat) {
                // 显示文件头用于调试
                const headerHex = Array.from(header.slice(0, 16))
                    .map(b => b.toString(16).padStart(2, '0'))
                    .join(' ');
                this.log(`警告: 未识别的文件格式，文件头: ${headerHex}`);
                this.log('将尝试处理，但可能失败');
            }
            
            return true;
            
        } catch (error) {
            throw new Error(`输入文件验证失败: ${error.message}`);
        }
    }

    // 使用FFmpeg进行优化
    async optimizeWithFFmpeg(inputFileName, outputFileName, onProgress) {
        this.log('开始FFmpeg优化处理...');
        
        // 检查输入文件是否存在
        try {
            const inputData = this.ffmpeg.FS('readFile', inputFileName);
            this.log(`输入文件确认存在: ${this.formatFileSize(inputData.length)}`);
        } catch (error) {
            throw new Error(`输入文件不存在: ${inputFileName} - ${error.message}`);
        }
        
        // 设置FFmpeg进度监听和错误收集
        let duration = 0;
        let ffmpegErrors = [];
        let hasError = false;
        
        this.ffmpeg.setLogger(({ type, message }) => {
            // 记录所有FFmpeg输出用于调试
            console.log(`FFmpeg [${type}]:`, message);
            
            if (type === 'fferr') {
                // 收集错误信息
                if (message.includes('Error') || message.includes('Invalid') || message.includes('failed')) {
                    ffmpegErrors.push(message);
                    hasError = true;
                    this.log(`FFmpeg错误: ${message}`);
                }
                
                // 解析持续时间
                const durationMatch = message.match(/Duration: (\d{2}):(\d{2}):(\d{2}\.\d{2})/);
                if (durationMatch) {
                    const [, hours, minutes, seconds] = durationMatch;
                    duration = parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseFloat(seconds);
                    this.log(`视频时长: ${hours}:${minutes}:${seconds}`);
                }

                // 解析当前进度
                const timeMatch = message.match(/time=(\d{2}):(\d{2}):(\d{2}\.\d{2})/);
                if (timeMatch && duration > 0) {
                    const [, hours, minutes, seconds] = timeMatch;
                    const currentTime = parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseFloat(seconds);
                    const progress = Math.min(currentTime / duration, 1);
                    onProgress(progress);
                }
                
                // 检查是否已经完成
                if (message.includes('video:') && message.includes('audio:') && message.includes('subtitle:')) {
                    this.log(`FFmpeg处理统计: ${message}`);
                }
            }
        });

        try {
            // 首先尝试标准的faststart命令
            this.log('执行命令: ffmpeg -i ' + inputFileName + ' -c copy -movflags faststart ' + outputFileName);
            await this.ffmpeg.run('-i', inputFileName, '-c', 'copy', '-movflags', 'faststart', outputFileName);
            
            this.log('FFmpeg命令执行完成');
            
        } catch (error) {
            this.log(`标准FFmpeg命令失败: ${error.message}`);
            
            // 清理可能的部分输出文件
            try {
                this.ffmpeg.FS('unlink', outputFileName);
            } catch (e) {
                // 忽略删除失败
            }
            
            // 尝试备用命令：不使用copy，重新编码
            this.log('尝试备用方案: 重新编码而非复制流...');
            ffmpegErrors = []; // 重置错误收集
            hasError = false;
            
            try {
                this.log('执行备用命令: ffmpeg -i ' + inputFileName + ' -movflags faststart ' + outputFileName);
                await this.ffmpeg.run('-i', inputFileName, '-movflags', 'faststart', outputFileName);
                this.log('备用FFmpeg命令执行完成');
                
            } catch (backupError) {
                this.log(`备用FFmpeg命令也失败: ${backupError.message}`);
                
                // 收集所有错误信息
                let errorDetails = `FFmpeg处理失败:\n`;
                errorDetails += `主要错误: ${error.message}\n`;
                errorDetails += `备用错误: ${backupError.message}\n`;
                
                if (ffmpegErrors.length > 0) {
                    errorDetails += `FFmpeg详细错误:\n`;
                    ffmpegErrors.forEach(err => errorDetails += `  - ${err}\n`);
                }
                
                throw new Error(errorDetails);
            }
        }
        
        // 最终检查是否有错误警告
        if (hasError && ffmpegErrors.length > 0) {
            this.log('FFmpeg处理过程中的警告:');
            ffmpegErrors.forEach(error => this.log(`  - ${error}`));
        }
    }

    // 验证和获取结果
    async validateAndGetResult(outputFileName) {
        // 检查输出文件是否存在
        try {
            const outputData = this.ffmpeg.FS('readFile', outputFileName);
            this.log('输出文件大小: ' + this.formatFileSize(outputData.length));
            
            // 详细验证输出文件
            if (outputData.length === 0) {
                // 列出FFmpeg文件系统中的所有文件进行调试
                try {
                    const files = this.ffmpeg.FS('readdir', '/');
                    this.log('FFmpeg文件系统内容:');
                    files.forEach(file => {
                        if (file !== '.' && file !== '..' && file !== 'dev') {
                            try {
                                const fileData = this.ffmpeg.FS('readFile', file);
                                this.log(`  - ${file}: ${this.formatFileSize(fileData.length)}`);
                            } catch (e) {
                                this.log(`  - ${file}: 无法读取`);
                            }
                        }
                    });
                } catch (e) {
                    this.log('无法列出FFmpeg文件系统内容');
                }
                
                throw new Error('输出文件为空，FFmpeg处理可能失败。请检查输入文件格式是否正确。');
            }
            
            if (outputData.length < 1000) {
                throw new Error(`输出文件过小 (${outputData.length} bytes)，可能处理不完整`);
            }
            
            // 检查文件头是否为有效的视频格式
            const header = new Uint8Array(outputData.buffer.slice(0, Math.min(32, outputData.length)));
            let isValidVideo = false;
            
            // 检查常见视频格式标识
            for (let i = 0; i < header.length - 4; i++) {
                // 检查ftyp box (MP4)
                if (header[i] === 0x66 && header[i+1] === 0x74 && 
                    header[i+2] === 0x79 && header[i+3] === 0x70) {
                    isValidVideo = true;
                    break;
                }
            }
            
            if (!isValidVideo) {
                this.log('警告: 输出文件可能不是有效的视频格式');
                // 显示文件头用于调试
                const headerHex = Array.from(header.slice(0, 16))
                    .map(b => b.toString(16).padStart(2, '0'))
                    .join(' ');
                this.log(`文件头 (hex): ${headerHex}`);
            } else {
                this.log('✅ 输出文件格式验证通过');
            }
            
            return outputData;
            
        } catch (error) {
            if (error.message.includes('no such file')) {
                throw new Error(`输出文件不存在: ${outputFileName}。FFmpeg可能未能成功创建输出文件。`);
            }
            throw error;
        }
    }

    // 清理临时文件
    cleanupTempFiles(inputFileName, outputFileName) {
        try {
            this.ffmpeg.FS('unlink', inputFileName);
            this.ffmpeg.FS('unlink', outputFileName);
            this.log('临时文件已清理');
        } catch (cleanupError) {
            this.log('清理临时文件时出现警告: ' + cleanupError.message);
        }
    }

    getFileExtension(filename) {
        return filename.split('.').pop().toLowerCase();
    }

    createDownloadLink(data, originalName, outputName) {
        const blob = new Blob([data], { type: 'video/mp4' });
        const url = URL.createObjectURL(blob);

        const downloadBtn = document.getElementById('downloadBtn');
        // 使用传入的输出文件名，如果没有则使用默认命名
        const finalName = outputName || originalName.replace(/\.[^/.]+$/, '_optimized.$&');

        downloadBtn.onclick = () => {
            const a = document.createElement('a');
            console.log(url);
            a.href = url;
            a.download = finalName;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            this.log('文件已下载: ' + finalName);
        };
    }

    showProcessSection() {
        document.getElementById('processSection').style.display = 'block';
        document.getElementById('resultSection').style.display = 'none';
        document.getElementById('errorSection').style.display = 'none';
    }

    showResult() {
        document.getElementById('processSection').style.display = 'none';
        document.getElementById('resultSection').style.display = 'block';
        document.getElementById('errorSection').style.display = 'none';

        // 更新状态文本
        const statusText = document.getElementById('statusText');
        if (statusText) {
            statusText.textContent = '处理完成！可以下载优化后的视频';
            statusText.style.color = '#28a745';
        }

        // 重新启用选择按钮（为下次使用准备）
        const selectBtn = document.getElementById('selectBtn');
        if (selectBtn) {
            selectBtn.disabled = false;
            selectBtn.textContent = '选择视频文件';
        }
    }

    showError(message) {
        const errorMessage = document.getElementById('errorMessage');
        const statusText = document.getElementById('statusText');
        const selectBtn = document.getElementById('selectBtn');

        if (errorMessage) {
            errorMessage.textContent = message;
        }

        document.getElementById('processSection').style.display = 'none';
        document.getElementById('resultSection').style.display = 'none';
        document.getElementById('errorSection').style.display = 'block';

        // 更新状态文本
        if (statusText) {
            statusText.textContent = '处理失败: ' + message;
            statusText.style.color = '#dc3545';
        }

        // 重新启用选择按钮
        if (selectBtn) {
            selectBtn.disabled = false;
            selectBtn.textContent = '选择视频文件';
        }

        this.isProcessing = false;
    }

    updateProgress(percent, text) {
        const progressFill = document.getElementById('progressFill');
        const progressText = document.getElementById('progressText');
        const statusText = document.getElementById('statusText');

        if (progressFill) {
            progressFill.style.width = percent + '%';
        }

        if (progressText) {
            progressText.textContent = text || `处理中... ${percent}%`;
        }

        if (statusText) {
            statusText.textContent = text || `处理中... ${percent}%`;
        }

        // 更新进度条的 aria 属性
        const progressBar = document.querySelector('.progress-bar');
        if (progressBar) {
            progressBar.setAttribute('aria-valuenow', percent);
        }
    }



    // 智能选择最佳处理方法（基于内存和文件大小）
    async processFileWithBestMethod(file, fileName) {
        const availableMemory = this.getAvailableMemory();
        const strategy = this.selectProcessingStrategy(file.size, availableMemory);
        
        this.log(`文件大小: ${this.formatFileSize(file.size)}`);
        this.log(`可用内存: ${this.formatFileSize(availableMemory)}`);
        this.log(`选择策略: ${strategy}`);

        // 启动内存监控
        const memoryMonitor = this.startMemoryMonitoring();

        try {
            switch (strategy) {
                case 'direct':
                    this.log('使用直接处理策略');
                    await this.directProcess(file, fileName);
                    break;
                case 'chunked':
                    this.log('使用分块处理策略');
                    await this.chunkedProcess(file, fileName);
                    break;
                case 'streaming':
                    this.log('使用流式处理策略');
                    await this.streamingProcess(file, fileName);
                    break;
                case 'worker':
                    this.log('使用Worker多线程处理策略');
                    await this.workerProcess(file, fileName);
                    break;
                default:
                    throw new Error('无法处理此文件大小，建议使用桌面版FFmpeg');
            }
        } finally {
            clearInterval(memoryMonitor);
            this.cleanup();
        }
    }

    // 获取可用内存
    getAvailableMemory() {
        if ('memory' in performance) {
            return performance.memory.jsHeapSizeLimit - performance.memory.usedJSHeapSize;
        }
        return this.maxMemoryUsage; // 默认值
    }

    // 选择处理策略
    selectProcessingStrategy(fileSize, availableMemory) {
        const fileSizeGB = fileSize / (1024 * 1024 * 1024);
        const availableMemoryGB = availableMemory / (1024 * 1024 * 1024);

        if (fileSize < availableMemory * 0.3) {
            return 'direct'; // 直接处理：文件小于可用内存的30%
        } else if (fileSize < availableMemory * 0.8) {
            return 'chunked'; // 分块处理：文件小于可用内存的80%
        } else if (fileSizeGB < 3) {
            return 'streaming'; // 流式处理：文件小于3GB
        } else if (fileSizeGB < 5) {
            // 暂时使用流式处理替代Worker处理，避免Worker中的FFmpeg加载问题
            this.log('⚠️ 超大文件，使用流式处理（Worker处理暂时禁用）');
            return 'streaming';
        } else {
            return 'unsupported'; // 不支持
        }
    }

    // 启动内存监控
    startMemoryMonitoring() {
        return setInterval(() => {
            if ('memory' in performance) {
                const used = performance.memory.usedJSHeapSize;
                const limit = performance.memory.jsHeapSizeLimit;
                const percentage = used / limit;

                if (percentage > 0.85) {
                    this.log(`⚠️ 内存使用率过高: ${(percentage * 100).toFixed(1)}%`);
                    this.handleMemoryPressure();
                } else if (percentage > 0.7) {
                    this.log(`⚠️ 内存使用率较高: ${(percentage * 100).toFixed(1)}%`);
                }
            }
        }, 2000);
    }

    // 处理内存压力
    async handleMemoryPressure() {
        this.log('触发内存优化...');
        
        // 强制垃圾回收（如果可用）
        if (window.gc) {
            window.gc();
            this.log('执行垃圾回收');
        }

        // 暂停处理，等待内存释放
        await new Promise(resolve => setTimeout(resolve, 200));
        
        // 清理FFmpeg临时文件
        this.cleanupFFmpegFiles();
    }

    // 清理FFmpeg临时文件
    cleanupFFmpegFiles() {
        if (!this.ffmpeg) return;
        
        try {
            const files = this.ffmpeg.FS('readdir', '/');
            files.forEach(file => {
                if (file !== '.' && file !== '..' && file !== 'dev') {
                    try {
                        this.ffmpeg.FS('unlink', file);
                    } catch (e) {
                        // 忽略删除失败
                    }
                }
            });
            this.log('清理FFmpeg临时文件完成');
        } catch (error) {
            // 忽略清理错误
        }
    }

    // 直接处理策略
    async directProcess(file, fileName) {
        this.log('开始直接处理...');
        const fileData = new Uint8Array(await file.arrayBuffer());
        this.ffmpeg.FS('writeFile', fileName, fileData);
        this.log('文件写入FFmpeg完成');
    }

    // 分块处理策略
    async chunkedProcess(file, fileName) {
        this.log('开始分块处理...');
        const chunks = Math.ceil(file.size / this.chunkSize);
        this.log(`分块数量: ${chunks}, 每块大小: ${this.formatFileSize(this.chunkSize)}`);

        // 创建空文件
        this.ffmpeg.FS('writeFile', fileName, new Uint8Array(0));

        for (let i = 0; i < chunks; i++) {
            const start = i * this.chunkSize;
            const end = Math.min(start + this.chunkSize, file.size);
            const chunk = file.slice(start, end);

            this.log(`处理分块 ${i + 1}/${chunks}`);
            this.updateProgress(20 + (i / chunks) * 15, `处理分块 ${i + 1}/${chunks}...`);

            const chunkData = new Uint8Array(await chunk.arrayBuffer());
            
            // 读取现有文件并追加
            let existingData;
            try {
                existingData = this.ffmpeg.FS('readFile', fileName);
            } catch (e) {
                existingData = new Uint8Array(0);
            }

            const newData = new Uint8Array(existingData.length + chunkData.length);
            newData.set(existingData);
            newData.set(chunkData, existingData.length);

            this.ffmpeg.FS('writeFile', fileName, newData);

            // 清理内存
            chunkData.fill(0);
            newData.fill(0);

            // 每处理几个块就检查内存
            if (i % 3 === 0) {
                await new Promise(resolve => setTimeout(resolve, 50));
                if (window.gc) window.gc();
            }
        }
        this.log('分块处理完成');
    }

    // 流式处理策略
    async streamingProcess(file, fileName) {
        this.log('开始流式处理...');
        
        if (!('ReadableStream' in window)) {
            throw new Error('浏览器不支持ReadableStream，降级到分块处理');
        }

        const stream = file.stream();
        const reader = stream.getReader();
        let processedSize = 0;

        // 创建空文件
        this.ffmpeg.FS('writeFile', fileName, new Uint8Array(0));

        try {
            while (true) {
                const { done, value } = await reader.read();
                if (done) break;

                // 处理当前块
                let existingData;
                try {
                    existingData = this.ffmpeg.FS('readFile', fileName);
                } catch (e) {
                    existingData = new Uint8Array(0);
                }

                const newData = new Uint8Array(existingData.length + value.length);
                newData.set(existingData);
                newData.set(value, existingData.length);

                this.ffmpeg.FS('writeFile', fileName, newData);

                processedSize += value.length;
                const progress = (processedSize / file.size) * 15;
                this.updateProgress(20 + progress, `流式处理 ${this.formatFileSize(processedSize)}/${this.formatFileSize(file.size)}...`);

                // 清理内存
                newData.fill(0);

                // 定期检查内存压力
                if (processedSize % (32 * 1024 * 1024) === 0) { // 每32MB检查一次
                    await new Promise(resolve => setTimeout(resolve, 10));
                }
            }
        } catch (error) {
            this.log('流式处理出错: ' + error.message);
            throw error;
        } finally {
            reader.releaseLock();
        }

        this.log('流式处理完成');
    }

    // Worker多线程处理策略
    async workerProcess(file, fileName) {
        this.log('开始Worker多线程处理...');
        
        const self = this; // 保存this引用
        
        return new Promise((resolve, reject) => {
            const workerCode = `
                // Worker内部处理逻辑
                importScripts('https://unpkg.com/@ffmpeg/ffmpeg@0.10.1/dist/ffmpeg.min.js');
                
                let ffmpeg = null;
                
                self.onmessage = async function(e) {
                    const { type, file, fileName } = e.data;
                    
                    if (type === 'PROCESS_FILE') {
                        try {
                            self.postMessage({
                                type: 'PROGRESS',
                                progress: 0.1,
                                message: '初始化Worker FFmpeg...'
                            });
                            
                            // 初始化FFmpeg
                            if (!ffmpeg) {
                                ffmpeg = FFmpeg.createFFmpeg({ 
                                    log: false,
                                    corePath: 'https://unpkg.com/@ffmpeg/core@0.10.0/dist/ffmpeg-core.js'
                                });
                                await ffmpeg.load();
                            }
                            
                            self.postMessage({
                                type: 'PROGRESS',
                                progress: 0.3,
                                message: 'Worker读取文件数据...'
                            });
                            
                            // 处理文件
                            const fileData = new Uint8Array(await file.arrayBuffer());
                            
                            self.postMessage({
                                type: 'PROGRESS',
                                progress: 0.6,
                                message: 'Worker写入FFmpeg文件系统...'
                            });
                            
                            ffmpeg.FS('writeFile', fileName, fileData);
                            
                            self.postMessage({
                                type: 'PROGRESS',
                                progress: 0.9,
                                message: 'Worker处理完成'
                            });
                            
                            self.postMessage({
                                type: 'COMPLETE'
                            });
                            
                        } catch (error) {
                            self.postMessage({
                                type: 'ERROR',
                                error: error.message
                            });
                        }
                    }
                };
            `;

            const blob = new Blob([workerCode], { type: 'application/javascript' });
            const worker = new Worker(URL.createObjectURL(blob));

            worker.onmessage = (e) => {
                const { type, progress, message, error } = e.data;
                
                switch (type) {
                    case 'PROGRESS':
                        self.updateProgress(20 + progress * 15, message);
                        self.log(message);
                        break;
                    case 'COMPLETE':
                        worker.terminate();
                        URL.revokeObjectURL(blob);
                        resolve();
                        break;
                    case 'ERROR':
                        worker.terminate();
                        URL.revokeObjectURL(blob);
                        reject(new Error(error));
                        break;
                }
            };

            worker.onerror = (error) => {
                worker.terminate();
                URL.revokeObjectURL(blob);
                reject(error);
            };

            // 发送文件给Worker处理
            worker.postMessage({
                type: 'PROCESS_FILE',
                file: file,
                fileName: fileName
            });
        });
    }

    // 清理资源
    cleanup() {
        // 清理Workers
        this.workers.forEach(worker => {
            worker.terminate();
        });
        this.workers = [];

        // 强制垃圾回收
        if (window.gc) {
            window.gc();
        }
    }

    // 流式写入大文件到FFmpeg
    async writeFileStreamToFFmpeg(file, fileName) {
        const chunkSize = 8 * 1024 * 1024; // 8MB 分块，更小的内存占用
        const chunks = Math.ceil(file.size / chunkSize);

        this.log(`开始流式写入文件，共 ${chunks} 块，每块 ${this.formatFileSize(chunkSize)}`);

        // 创建空文件
        this.ffmpeg.FS('writeFile', fileName, new Uint8Array(0));

        for (let i = 0; i < chunks; i++) {
            const start = i * chunkSize;
            const end = Math.min(start + chunkSize, file.size);
            const chunk = file.slice(start, end);

            this.log(`写入第 ${i + 1}/${chunks} 块 (${this.formatFileSize(start)} - ${this.formatFileSize(end)})`);
            this.updateProgress(20 + (i / chunks) * 15, `写入文件块 ${i + 1}/${chunks}...`);
            this.logMemoryUsage(`写入块 ${i + 1}`);

            try {
                const arrayBuffer = await chunk.arrayBuffer();
                const chunkData = new Uint8Array(arrayBuffer);

                // 读取现有文件内容
                let existingData;
                try {
                    existingData = this.ffmpeg.FS('readFile', fileName);
                } catch (e) {
                    existingData = new Uint8Array(0);
                }

                // 合并数据
                const newData = new Uint8Array(existingData.length + chunkData.length);
                newData.set(existingData);
                newData.set(chunkData, existingData.length);

                // 写回文件
                this.ffmpeg.FS('writeFile', fileName, newData);

                // 清理内存
                existingData = null;
                chunkData.fill(0);
                newData.fill(0);

                // 强制垃圾回收
                if (i % 3 === 0 && window.gc) {
                    window.gc();
                }

                // 给浏览器时间处理
                await new Promise(resolve => setTimeout(resolve, 10));

            } catch (error) {
                throw new Error(`写入文件块 ${i + 1} 失败: ${error.message}`);
            }
        }

        this.log('文件流式写入完成');
        this.logMemoryUsage('流式写入完成');
    }

    // 分块读取大文件（备用方案）
    async readFileInChunks(file) {
        // 对于超大文件，不再尝试分配完整内存
        if (file.size > 2 * 1024 * 1024 * 1024) { // 2GB以上
            throw new Error(`文件过大 (${this.formatFileSize(file.size)})，浏览器无法分配足够的连续内存。建议使用桌面版 FFmpeg 或将文件分割后处理。`);
        }

        // 根据文件大小动态调整分块大小
        let chunkSize = 16 * 1024 * 1024; // 16MB
        if (file.size > 1024 * 1024 * 1024) { // 1GB以上使用更小的分块
            chunkSize = 8 * 1024 * 1024; // 8MB
        }

        const chunks = Math.ceil(file.size / chunkSize);
        this.log(`开始分块读取文件，共 ${chunks} 块，每块 ${this.formatFileSize(chunkSize)}`);

        // 使用更保守的内存分配策略
        let result;
        try {
            result = new Uint8Array(file.size);
        } catch (error) {
            throw new Error(`无法分配内存：文件过大 (${this.formatFileSize(file.size)})，建议使用桌面版 FFmpeg 处理`);
        }

        let offset = 0;

        for (let i = 0; i < chunks; i++) {
            const start = i * chunkSize;
            const end = Math.min(start + chunkSize, file.size);
            const chunk = file.slice(start, end);

            this.log(`读取第 ${i + 1}/${chunks} 块 (${this.formatFileSize(start)} - ${this.formatFileSize(end)})`);
            this.updateProgress(20 + (i / chunks) * 10, `读取文件块 ${i + 1}/${chunks}...`);
            this.logMemoryUsage(`读取块 ${i + 1}`);

            try {
                const arrayBuffer = await chunk.arrayBuffer();
                const chunkData = new Uint8Array(arrayBuffer);
                result.set(chunkData, offset);
                offset += chunkData.length;

                // 清理临时引用
                chunkData.fill(0);

                // 给浏览器更多时间来处理垃圾回收
                if (i % 3 === 0) {
                    await new Promise(resolve => setTimeout(resolve, 50));
                    if (window.gc) {
                        window.gc();
                    }
                }
            } catch (error) {
                // 清理已分配的内存
                if (result) {
                    result.fill(0);
                    result = null;
                }
                throw new Error(`读取文件块 ${i + 1} 失败: ${error.message}`);
            }
        }

        this.log('文件分块读取完成');
        this.logMemoryUsage('分块读取完成');
        return result;
    }

    log(message) {
        const logOutput = document.getElementById('logOutput');
        const timestamp = new Date().toLocaleTimeString();
        logOutput.textContent += `[${timestamp}] ${message}\n`;
        logOutput.scrollTop = logOutput.scrollHeight;
    }
}

// 重置应用
function resetApp() {
    // 重置UI显示
    document.getElementById('fileInfo').style.display = 'none';
    document.getElementById('processSection').style.display = 'none';
    document.getElementById('resultSection').style.display = 'none';
    document.getElementById('errorSection').style.display = 'none';
    document.getElementById('fileInput').value = '';
    document.getElementById('logOutput').textContent = '';

    // 重置进度条
    const progressFill = document.getElementById('progressFill');
    const progressText = document.getElementById('progressText');
    if (progressFill) progressFill.style.width = '0%';
    if (progressText) progressText.textContent = '准备中...';

    // 重新启用选择按钮
    const selectBtn = document.getElementById('selectBtn');
    if (selectBtn) {
        selectBtn.disabled = false;
        selectBtn.textContent = '选择视频文件';
    }

    // 重置状态文本
    const statusText = document.getElementById('statusText');
    if (statusText) {
        statusText.textContent = 'FFmpeg 已就绪，可以选择文件';
        statusText.style.color = '';
    }

    // 重置全局实例状态
    if (window.videoOptimizerInstance) {
        window.videoOptimizerInstance.currentFile = null;
        window.videoOptimizerInstance.isProcessing = false;
    }
}

// 初始化应用
document.addEventListener('DOMContentLoaded', () => {
    window.videoOptimizerInstance = new WebVideoOptimizer();
});